我們接下來要編寫顯示全體用戶的email的頁面,之後會作為登入後才能查看的頁面,這部分大家應該都很熟悉了,可以參考第四個專案。
//UserService.java
public List<User> getAllUsers() {
return userRepository.findAll();
}
//AuthController.java
//顯示全體用戶email的網頁
@GetMapping("/users")
public String users(Model model) {
List<User> users = userService.getAllUsers();
model.addAttribute("users", users);
return "users";
}
//users.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User Registration System</title>
</head>
<body>
<div>
<div>
<a th:href="@{/}">Home</a>
</div>
<div>
<h1>List of User</h1>
</div>
<table>
<thead>
<tr>
<th>User ID</th>
<th>User Email</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.email}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
啟動專案,前往http://localhost:8080/users,查看結果。
不用登入也沒有權限驗證,就能自由觀看這些機密資料,感覺有資料外洩的危機,應該要改成登入後才能觀看。
下個部分我們來開發登入功能
在AuthController.java添加進入登入頁面功能
//顯示登入頁面
@GetMapping("/login")
public String login(Model model) {
return "login";
}
設定登入頁面的內容
//login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User Registration System</title>
</head>
<body>
<div>
<div>
<a th:href="@{/}">Home</a>
<a th:href="@{/register}">Register</a>
</div>
<div>
<form method="post" role="form" th:action="@{/login}">
<div>
<label>User Email</label>
<input placeholder="Enter user email" type="text" id="email" name="email" />
</div>
<div>
<label>User Password</label>
<input placeholder="Enter user password" type="text" id="password" name="password" />
</div>
<button type="submit">Login</button>
<span>Not registered? <a th:href="@{/register}">Register</a></span>
</form>
</div>
</div>
</body>
</html>
跨站請求偽造(Cross-Site Request Forgery)是一種網路攻擊方式,如果在許多網站維持登入的狀態就有可能發生被CSRF的情況。
如果你相信了,點擊以上連結,你就有可能在不知不覺中被CSRF攻擊了,打開的網站看似無害,實際上已經偷偷使用HTTP request method的GET進行一些危險操作。
這邊提供的範例是無害的,不過還是建議大家不要隨便點擊不明的連結。
為了避免有人成為受害者,專案管理員可以採取以下措施:
Spring Security的設定就像一個鑰匙串,需要的功能就串上去,最後變成一大串。
在src/main/java/com/user_registration_system/user_registration_system/Config中,新增AppConfig.java。
@Configuration代表告知Spring,這些內容是用來管理專案的設定
//AppConfig.java
@Configuration
public class AppConfig {
@Bean
用來管理Spring Security的權限設定
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
雖然之前說CSRF很恐怖,但我們不是銀行管理專案,不需要CSRF保護,將CSRF防護關閉。
http.csrf(csrf -> csrf.disable())
權限管理,符合/users/開頭的內容(authorizeRequests.requestMatchers("/users/")需要登入(.authenticated())才能存取
其餘的(.anyRequest())可以直接通過(.permitAll()),無需登入
這邊提供一些範例
⚠️代表要登入,✅代表無需登入
.authorizeHttpRequests(authorizeRequests -> authorizeRequests.requestMatchers("/users/**")
.authenticated()
.anyRequest()
.permitAll())
使用預設的Spring Security驗證方式
.httpBasic(Customizer.withDefaults())
登入表單的位置在/login
.formLogin(form -> form.loginPage("/login"))
登入的username欄位是email,這邊需要和login.html中欄位的id和name對應,否則找不到username
.usernameParameter("email")
登入的password欄位是password,需要對應login.html的欄位
.passwordParameter("password")
Spring Security會攔截POST /login的request,用來進行登入網站
.loginProcessingUrl("/login")
登入成功後,會轉移到/users
.defaultSuccessUrl("/users").permitAll());
return http.build();
}
}
我們還沒有導入自己的驗證系統,現在使用的是Spring Security預設的驗證系統。
啟動專案
我們要使用Spring Security提供的用戶名和密碼才能登入,用戶名是user,密碼需要在專案的控制台查看,類似
Using generated security password: 63df88fa-ecb9-4512-ae09-176864903b2f
每次產生的密碼都不相同,僅供測試使用。
我們也能自行設定用戶名和密碼,在application.properties添加
spring.security.user.name=user
spring.security.user.password=pw
現在我們每次都能使用固定的用戶名和密碼登入了。